home *** CD-ROM | disk | FTP | other *** search
/ Space & Astronomy / Space and Astronomy (October 1993).iso / mac / VIEWERS / X11 / XLOADIMG.TAR / pbm.c < prev    next >
C/C++ Source or Header  |  1991-05-20  |  11KB  |  461 lines

  1. /* pbm.c:
  2.  *
  3.  * portable bit map (pbm) format images
  4.  *
  5.  * jim frost 09.27.89
  6.  *
  7.  * patched by W. David Higgins (wdh@mkt.csd.harris.com) to support
  8.  * raw-format PBM files.
  9.  *
  10.  * patched by Ian MacPhedran (macphed@dvinci.usask.ca) to support
  11.  * PGM and PPM files (03-July-1990)
  12.  */
  13.  
  14. #include "image.h"
  15. #include "pbm.h"
  16.  
  17. /* SUPPRESS 558 */
  18.  
  19. static int          IntTable[256];
  20. static unsigned int Initialized= 0;
  21.  
  22. #define NOTINT  -1
  23. #define COMMENT -2
  24. #define SPACE   -3
  25. #define NEWLINE -4
  26.  
  27. #define BADREAD    0 /* read error */
  28. #define NOTPBM     1 /* not a pbm file */
  29. #define PBMNORMAL  2 /* pbm normal type file */
  30. #define PBMCOMPACT 3 /* pbm compacty type file */
  31. #define PBMRAWBITS 4 /* pbm raw bits type file */
  32. #define PGMNORMAL  5 /* pgm normal type file */
  33. #define PGMRAWBITS 6 /* pgm raw bytes type file */
  34. #define PPMNORMAL  7 /* ppm normal type file */
  35. #define PPMRAWBITS 8 /* ppm raw bytes type file */
  36.  
  37. static void initializeTable()
  38. { unsigned int a;
  39.  
  40.   for (a= 0; a < 256; a++)
  41.     IntTable[a]= NOTINT;
  42.   IntTable['#']= COMMENT;
  43.   IntTable['\n']= NEWLINE;
  44.   IntTable['\r']= IntTable['\t']= IntTable[' ']= SPACE;
  45.   IntTable['0']= 0;
  46.   IntTable['1']= 1;
  47.   IntTable['2']= 2;
  48.   IntTable['3']= 3;
  49.   IntTable['4']= 4;
  50.   IntTable['5']= 5;
  51.   IntTable['6']= 6;
  52.   IntTable['7']= 7;
  53.   IntTable['8']= 8;
  54.   IntTable['9']= 9;
  55.   Initialized= 1;
  56. }
  57.  
  58. static int pbmReadChar(zf)
  59.      ZFILE *zf;
  60. { int c;
  61.  
  62.   if ((c= zgetc(zf)) == EOF) {
  63.     zclose(zf);
  64.     return(-1);
  65.   }
  66.   if (IntTable[c] == COMMENT)
  67.     do {
  68.       if ((c= zgetc(zf)) == EOF)
  69.     return(-1);
  70.     } while (IntTable[c] != NEWLINE);
  71.   return(c);
  72. }
  73.  
  74. static int pbmReadInt(zf)
  75.      ZFILE *zf;
  76. { int c, value;
  77.  
  78.   for (;;) {
  79.     c= pbmReadChar(zf);
  80.     if (c < 0)
  81.       return(-1);
  82.     if (IntTable[c] >= 0)
  83.       break;
  84.   };
  85.  
  86.   value= IntTable[c];
  87.   for (;;) {
  88.     c= pbmReadChar(zf);
  89.     if (c < 0)
  90.       return(-1);
  91.     if (IntTable[c] < 0)
  92.       return(value);
  93.     value= (value * 10) + IntTable[c];
  94.   }
  95. }
  96.  
  97. static int isPBM(zf, name, width, height, maxval, verbose)
  98.      ZFILE        *zf;
  99.      char         *name;
  100.      unsigned int *width, *height, *maxval;
  101.      unsigned int  verbose;
  102. { byte buf[4];
  103.  
  104.   if (! Initialized)
  105.     initializeTable();
  106.  
  107.   if (zread(zf, buf, 2) != 2)
  108.     return(NOTPBM);
  109.   if (memToVal((byte *)buf, 2) == memToVal((byte *)"P1", 2)) {
  110.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  111.       return(NOTPBM);
  112.     *maxval = 1;
  113.     if (verbose)
  114.       printf("%s is a %dx%d PBM image\n", name, *width, *height);
  115.     return(PBMNORMAL);
  116.   }
  117.   if (memToVal((byte *)buf, 2) == memToVal((byte *)"P4", 2)) {
  118.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  119.       return(NOTPBM);
  120.     *maxval = 1;
  121.     if (verbose)
  122.       printf("%s is a %dx%d RawBits PBM image\n", name, *width, *height);
  123.     return(PBMRAWBITS);
  124.   }
  125.   if (memToVal(buf, 2) == 0x2a17) {
  126.     if (zread(zf, buf, 4) != 4)
  127.       return(NOTPBM);
  128.     *width= memToVal((byte *)buf, 2);
  129.     *height= memToVal((byte *)(buf + 2), 2);
  130.     *maxval = 1;
  131.     if (verbose)
  132.       printf("%s is a %dx%d Compact PBM image\n", name, *width, *height);
  133.     return(PBMCOMPACT);
  134.   }
  135.   if (memToVal(buf, 2) == memToVal((byte *)"P2", 2)) {
  136.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  137.       return(NOTPBM);
  138.     *maxval = pbmReadInt(zf);
  139.     if (verbose)
  140.       printf("%s is a %dx%d PGM image with %d levels\n", name, *width,
  141.     *height, (*maxval+1));
  142.     return(PGMNORMAL);
  143.   }
  144.   if (memToVal(buf, 2) == memToVal((byte *)"P5", 2)) {
  145.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  146.       return(NOTPBM);
  147.     *maxval = pbmReadInt(zf);
  148.     if (verbose)
  149.       printf("%s is a %dx%d Raw PGM image with %d levels\n", name, *width,
  150.     *height, (*maxval+1));
  151.     return(PGMRAWBITS);
  152.   }
  153.   if (memToVal(buf, 2) == memToVal((byte *)"P3", 2)) {
  154.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  155.       return(NOTPBM);
  156.     *maxval = pbmReadInt(zf);
  157.     if (verbose)
  158.       printf("%s is a %dx%d PPM image with %d levels\n", name, *width,
  159.     *height, (*maxval+1));
  160.     return(PPMNORMAL);
  161.   }
  162.   if (memToVal(buf, 2) == memToVal((byte *)"P6", 2)) {
  163.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  164.       return(NOTPBM);
  165.     *maxval = pbmReadInt(zf);
  166.     if (verbose)
  167.       printf("%s is a %dx%d Raw PPM image with %d levels\n", name, *width,
  168.     *height, (*maxval+1));
  169.     return(PPMRAWBITS);
  170.   }
  171.   return(NOTPBM);
  172. }
  173.  
  174. int pbmIdent(fullname, name)
  175.      char *fullname, *name;
  176. { ZFILE        *zf;
  177.   unsigned int  width, height, maxval, ret;
  178.  
  179.   if (! (zf= zopen(fullname)))
  180.     return(0);
  181.  
  182.   ret= isPBM(zf, name, &width, &height, &maxval, (unsigned int)1);
  183.   zclose(zf);
  184.   return(ret != NOTPBM);
  185. }
  186.  
  187. Image *pbmLoad(fullname, name, verbose)
  188.      char         *fullname, *name;
  189.      unsigned int  verbose;
  190. { ZFILE        *zf;
  191.   Image        *image;
  192.   int           pbm_type;
  193.   unsigned int  x, y;
  194.   unsigned int  width, height, maxval, depth;
  195.   unsigned int  linelen;
  196.   byte          srcmask, destmask;
  197.   byte         *destptr, *destline;
  198.   int           src, size;
  199.   unsigned int  numbytes, numread;
  200.   int           red, grn, blu;
  201.  
  202.   if (! (zf= zopen(fullname)))
  203.     return(NULL);
  204.  
  205.   pbm_type= isPBM(zf, name, &width, &height, &maxval, verbose);
  206.   if (pbm_type == NOTPBM) {
  207.     zclose(zf);
  208.     return(NULL);
  209.   }
  210.   znocache(zf);
  211.   switch (pbm_type) {
  212.   case PBMNORMAL:
  213.     image= newBitImage(width, height);
  214.     linelen= (width / 8) + (width % 8 ? 1 : 0);
  215.     destline= image->data;
  216.     for (y= 0; y < height; y++) {
  217.       destptr= destline;
  218.       destmask= 0x80;
  219.       for (x= 0; x < width; x++) {
  220.     do {
  221.       if ((src= pbmReadChar(zf)) < 0) {
  222.         printf("%s: Short image\n", fullname);
  223.         zclose(zf);
  224.         exit(1);
  225.       }
  226.       if (IntTable[src] == NOTINT) {
  227.         printf("%s: Bad image data\n", fullname);
  228.         zclose(zf);
  229.         exit(1);
  230.       }
  231.     } while (IntTable[src] < 0);
  232.     
  233.     switch (IntTable[src]) {
  234.     case 1:
  235.       *destptr |= destmask;
  236.     case 0:
  237.       if (! (destmask >>= 1)) {
  238.         destmask= 0x80;
  239.         destptr++;
  240.       }
  241.       break;
  242.     default:
  243.       printf("%s: Bad image data\n", fullname);
  244.       zclose(zf);
  245.       exit(1);
  246.     }
  247.       }
  248.       destline += linelen;
  249.     }
  250.     break;
  251.  
  252.   case PBMRAWBITS:
  253.     image= newBitImage(width, height);
  254.     destline= image->data;
  255.     linelen= (width + 7) / 8;
  256.     numbytes= linelen * height;
  257.     srcmask= 0;        /* force initial read */
  258.     numread= 0;
  259.     for (y= 0; y < height; y++) {
  260.       destptr= destline;
  261.       destmask= 0x80;
  262.       if (srcmask != 0x80) {
  263.         srcmask= 0x80;
  264.     if ((numread < numbytes) && ((src= zgetc(zf)) == EOF)) {
  265.        printf("%s: Short image\n", fullname);
  266.        zclose(zf);
  267.        exit(1);
  268.     }
  269.     numread++;
  270.       }
  271.       for (x= 0; x < width; x++) {
  272.     if (src & srcmask)
  273.       *destptr |= destmask;
  274.     if (! (destmask >>= 1)) {
  275.       destmask= 0x80;
  276.       destptr++;
  277.     }
  278.     if (! (srcmask >>= 1)) {
  279.       srcmask= 0x80;
  280.       if ((numread < numbytes) && ((src= zgetc(zf)) == EOF)) {
  281.         printf("%s: Short image\n", fullname);
  282.         zclose(zf);
  283.         exit(1);
  284.       }
  285.       numread++;
  286.     }
  287.       }
  288.       destline += linelen;
  289.     }
  290.     break;
  291.  
  292.   case PBMCOMPACT:
  293.     image= newBitImage(width, height);
  294.     destline= image->data;
  295.     linelen= (width / 8) + (width % 8 ? 1 : 0);
  296.     srcmask= 0x80;
  297.     destmask= 0x80;
  298.     if ((src= zgetc(zf)) == EOF) {
  299.       printf("%s: Short image\n", fullname);
  300.       zclose(zf);
  301.       exit(1);
  302.     }
  303.     numread= 1;
  304.     numbytes= width * height;
  305.     numbytes= (numbytes / 8) + (numbytes % 8 ? 1 : 0);
  306.     for (y= 0; y < height; y++) {
  307.       destptr= destline;
  308.       destmask= 0x80;
  309.       for (x= 0; x < width; x++) {
  310.     if (src & srcmask)
  311.       *destptr |= destmask;
  312.     if (! (destmask >>= 1)) {
  313.       destmask= 0x80;
  314.       destptr++;
  315.     }
  316.     if (! (srcmask >>= 1)) {
  317.       srcmask= 0x80;
  318.       if ((numread < numbytes) && ((src= zgetc(zf)) == EOF)) {
  319.         printf("%s: Short image\n", fullname);
  320.         zclose(zf);
  321.         exit(1);
  322.       }
  323.       numread++;
  324.     }
  325.       }
  326.       destline += linelen;
  327.     }
  328.     break;
  329.   case PGMRAWBITS:
  330.     depth= colorsToDepth(maxval);
  331.     if (depth > 8)
  332.       image = newTrueImage(width, height);
  333.     else {
  334.       image = newRGBImage(width, height, depth);
  335.       for (y = 0; y <= maxval; y++)
  336.     { /* As in sunraster.c, use simple ramp for grey scale */
  337.       *(image->rgb.red + y) = PM_SCALE(y, maxval, 0xffff);
  338.       *(image->rgb.green + y) = PM_SCALE(y, maxval, 0xffff);
  339.       *(image->rgb.blue + y) = PM_SCALE(y, maxval, 0xffff);
  340.     }
  341.       image->rgb.used = maxval+1;
  342.     }
  343.     size= height * width;
  344.  
  345.     switch (image->type) {
  346.     case IRGB:
  347.  
  348.       /* read in the image in a chunk
  349.        */
  350.  
  351.       if (zread(zf, image->data, size) != size) {
  352.     printf("%s: Short image\n", fullname);
  353.     zclose(zf);
  354.     freeImage(image);
  355.     return(NULL);
  356.       }
  357.  
  358.       /* convert image values
  359.        */
  360.  
  361.       destptr = image->data;
  362.       for (y = 0; y < size; y++)
  363.     *(destptr++) = PM_SCALE(*destptr, maxval, 0xff);
  364.       break;
  365.  
  366.     case ITRUE:
  367.       for (y = 0; y < size; y++) {
  368.     if ((src = zgetc(zf)) == EOF) {
  369.       printf("%s: Short image\n", fullname);
  370.       zclose(zf);
  371.       freeImage(image);
  372.       return(NULL);
  373.     }
  374.     src = PM_SCALE(src, maxval, 0xff);
  375.     *(destptr++) = src; /* red */
  376.     *(destptr++) = src; /* green */
  377.     *(destptr++) = src; /* blue */
  378.       }
  379.       break;
  380.     }
  381.     break;
  382.   case PGMNORMAL:
  383.     depth= colorsToDepth(maxval);
  384.     if (depth > 8)
  385.       image= newTrueImage(width, height);
  386.     else {
  387.       image= newRGBImage(width, height, depth);
  388.       for (y= 0; y <= maxval; y++)
  389.     { /* As in sunraster.c, use simple ramp for grey scale */
  390.       *(image->rgb.red + y) = PM_SCALE(y, maxval, 0xffff);
  391.       *(image->rgb.green + y) = PM_SCALE(y, maxval, 0xffff);
  392.       *(image->rgb.blue + y) = PM_SCALE(y, maxval, 0xffff);
  393.     }
  394.       image->rgb.used = maxval+1;
  395.     }
  396.     destptr= image->data;
  397.     size= height * width;
  398.     for (y= 0; y < size; y++) {
  399.       if ((src = pbmReadInt(zf)) < 0)
  400.     {
  401.       printf("%s: Short image\n", fullname);
  402.       zclose(zf);
  403.       exit(1);
  404.     }
  405.       else {
  406.     src= PM_SCALE(src, maxval, 0xff);
  407.     if (TRUEP(image)) {
  408.       *(destptr++) = src; /* red */
  409.       *(destptr++) = src; /* green */
  410.       *(destptr++) = src; /* blue */
  411.     }
  412.     else
  413.       *(destptr++) = src;
  414.       }
  415.     }
  416.     break;
  417.  
  418.   case PPMRAWBITS:
  419.  
  420.     /* this is nice because the bit format is exactly what we want except
  421.      * for scaling.
  422.      */
  423.  
  424.     image= newTrueImage(width, height);
  425.     size= height * width * 3;
  426.     if (zread(zf, image->data, size) != size) {
  427.       printf("%s: Short image\n", fullname);
  428.       zclose(zf);
  429.       freeImage(image);
  430.       return(NULL);
  431.     }
  432.     destptr= image->data;
  433.     for (y= 0; y < size; y++) {
  434.       *destptr= PM_SCALE(*destptr, maxval, 0xff);
  435.       destptr++;
  436.     }
  437.     break;
  438.   case PPMNORMAL:
  439.     image= newTrueImage(width, height);
  440.     size= height * width;
  441.     destptr= image->data;
  442.     for (y= 0; y < size; y++) {
  443.       if (((red= pbmReadInt(zf)) == EOF) ||
  444.       ((grn= pbmReadInt(zf)) == EOF) ||
  445.       ((blu= pbmReadInt(zf)) == EOF))
  446.     {
  447.       printf("%s: Short image\n", fullname);
  448.       zclose(zf);
  449.       exit(1);
  450.     }
  451.       *(destptr++)= PM_SCALE(red, maxval, 0xff);
  452.       *(destptr++)= PM_SCALE(grn, maxval, 0xff);
  453.       *(destptr++)= PM_SCALE(blu, maxval, 0xff);
  454.     }
  455.     break;
  456.   }
  457.   image->title= dupString(name);
  458.   zclose(zf);
  459.   return(image);
  460. }
  461.